package edu.mapi.ir.gui.colormaps;

import java.awt.Color;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;

public class InterpolationColorMap implements ColorMap {

	private double[] values = new double[] {0f, 1f};
	private Color[] colors = new Color[] {Color.BLACK, Color.WHITE};
	private boolean debug = false;
	
	public InterpolationColorMap(double[] values, Color[] colors) {
		if (values.length != colors.length) {
			System.err.println("The values[] and colors[] sizes don't match!");
			return;
		}
		this.values = values;
		this.colors = colors;
	}
	
	@SuppressWarnings("unchecked")
    public InterpolationColorMap(String filename) throws FileNotFoundException, IOException {
		
		BufferedReader br = new BufferedReader(new FileReader(new File(filename)));

		Hashtable cmap = new Hashtable();
		String line;
		while ((line = br.readLine()) != null) {
			
			if (line.charAt(0) == '#')
				continue;
			
			StringTokenizer st = new StringTokenizer(line, " \t,");
			
			Double val = new Double(st.nextToken());
			int r = Integer.parseInt(st.nextToken());
			int g = Integer.parseInt(st.nextToken());
			int b = Integer.parseInt(st.nextToken());
			
			cmap.put(val, new Color(r,g,b));
			
			if (debug)
				System.out.println(val+"=("+r+","+g+","+b+")");
			
			double[] values = new double[cmap.size()];
			int i = 0;
			for (Enumeration e = cmap.keys(); e.hasMoreElements(); ) {
				values[i++] = ((Double)e.nextElement()).doubleValue();
			}
			
			Arrays.sort(values);
			
			Color[] colors = new Color[cmap.size()];
			
			for (i = 0; i < colors.length; i++) {
				colors[i] = (Color) cmap.get(new Double(values[i]));
			}
			
			this.values = values;
			this.colors = colors;
		}
	}
	
	public static void main(String args[]) throws Exception {
		ColorMap cmap = new InterpolationColorMap("c:/cmap.txt");
		System.out.println(cmap.getColor(0.1f));
	}
	
	public Color getColor(double value) {	
		if (debug)
			System.out.println("getColor()");
		
		value = Math.min(value, values[values.length-1]);
		value = Math.max(value, values[0]);
		
		int pos = 0;
		while (pos < values.length && value > values[pos])
			pos++;
		
		if (pos == 0)
			return colors[0];
		else if (pos == values.length)
			return colors[values.length-1];
		else {
			return interpolate(values[pos-1], colors[pos-1], value, values[pos], colors[pos]);
		}
	}
	
	private Color interpolate(double belowValue, Color belowColor, double value, double aboveValue, Color aboveColor) {
		
		if (debug)
			System.out.println("interpolate()");
		
		double totalDist = aboveValue - belowValue;
		
		double aboveDist = (value - belowValue) / totalDist;
		double belowDist = (aboveValue - value) / totalDist;
		
		if (debug)
			System.out.println("aboveDist="+aboveDist+", belowDist="+belowDist);
		
		return new Color(
			(int) (belowColor.getRed() * belowDist + aboveColor.getRed() * aboveDist),
			(int) (belowColor.getGreen() * belowDist + aboveColor.getGreen() * aboveDist),
			(int) (belowColor.getBlue() * belowDist + aboveColor.getBlue() * aboveDist)
		);
	} 
}
